-- UITopMenu
-- Create by weism
-- 主界面的顶部信息栏

require "game/ui/UIConsts"
require "game/ui/form/setting/UISystemSetting"

local ITEM_ID_STATUE = 10001;
local ITEM_ID_GEAR = 7405;

-- 第一栏类型
TOPMENU_FRAME_MONEY              = 1;   -- 金币
TOPMENU_FRAME_TREE               = 2;
TOPMENU_FRAME_SP                 = 3;   -- 探索点
TOPMENU_FRAME_COPPER             = 4;   -- 折弯的铜币信息
TOPMENU_FRAME_AIRSHIP_SCORE      = 5;
TOPMENU_FRAME_FIRST_RUINS_SCRAP  = 6;
TOPMENU_FRAME_RELIC_FRAGMENT     = 7;
TOPMENU_FRAME_GEAR               = 8;
TOPMENU_FRAME_LADADUOMU_COIN     = 9;    -- 拉达多姆金币
TOPMENU_FRAME_ACTIVITY_DATA      = 10;   -- 天空活动数据
TOPMENU_FRAME_ACTIVITY_EXCHANGE  = 101;  -- 活动兑换
TOPMENU_FRAME_FATE_CHAIN         = 102;  -- 命运的链达成

-- 第二栏类型
TOPMENU_FRAME_LIFE               = 11;   -- 体力
TOPMENU_FRAME_FRUIT              = 12;   -- 世界树果实
TOPMENU_FRAME_WORKER             = 13;   -- 工匠
TOPMENU_FRAME_GEM                = 14;   -- 钻石
TOPMENU_FRAME_HERO               = 15;
TOPMENU_FRAME_FEED               = 16;
TOPMENU_FRAME_AIRSHIP_ATTRIB     = 17;
TOPMENU_FRAME_AIRSHIP_RADAR      = 18;
TOPMENU_FRAME_RUINS_SCRAP        = 19;
TOPMENU_FRAME_FIGHT_ABILITY      = 20;
TOPMENU_FRAME_STATUE             = 21;
TOPMENU_FRAME_AIRSHIP_ATTRIB2    = 22;
TOPMENU_FRAME_ACTIVITY_TIMES     = 23;   -- 天空活动参与次数
TOPMENU_FRAME_ENGINEERING_MANUAL = 24;   -- 工程学手册
TOPMENU_FRAME_ROTINE_ACTIVITY    = 25;   -- 常规活动
TOPMENU_FRAME_FATE_LINK          = 26;   -- 命运的链次数

-- 左侧的头像框
TOPMENU_FRAME_HEAD_SLIME    = 1;
TOPMENU_FRAME_HEAD_AIRSHIP  = 2;

UITopMenu = class("UITopMenu", function()
    return cc.Layer:create();
end);

function UITopMenu.create()
    return UITopMenu.new();
end

local skyActivityId = -1;
local exchangeCurrency;

-- 内部函数声明
local redraw;
local calcDigit;

-- 构造函数
function UITopMenu:ctor()
    self:setName("UITopMenu");

    local node = cc.CSLoader:createNode("layout/main/TopMenu.csb");
    self.node = node;
    self:addChild(node);
    self:setLocalZOrder(UIMgr.TOP_MENU_ZORDER);

    self.lifeLeftTimeNode = findChildByName(self.node, "TOP/life_frame/recovery_left_time");
    self.fateLinkTimeNode = findChildByName(self.node, "TOP/fate_link_frame/recovery_left_time");
    self:setTopMenuTextStyle2(self.lifeLeftTimeNode);
    self:setTopMenuTextStyle2(self.fateLinkTimeNode);

    self.activityTimesRecoverTimeNode = findChildByName(self.node, "TOP/activity_times_frame/recovery_left_time");
    self:setTopMenuTextStyle2(self.activityTimesRecoverTimeNode);

    -- 当前钻石数量
    self.gemAmount = ME.user:queryAttrib("gem");

    -- 注册事件处理回调函数
    self:registerEventCallback()

    -- 注册点击事件
    self:registerTouchEvent();

    -- 记录第二栏各个节点
    local lifeNode   = findChildByName(self.node, "TOP/life_frame");
    local fruitNode  = findChildByName(self.node, "TOP/fruit_frame");
    local workerNode = findChildByName(self.node, "TOP/worker_frame");
    local gemNode    = findChildByName(self.node, "TOP/gem_frame");
    local heroNode   = findChildByName(self.node, "TOP/hero_frame");
    local feedNode   = findChildByName(self.node, "TOP/feed_frame");
    local airShipAttribNode = findChildByName(self.node, "TOP/airship_attrib_frame");
    local airshipRadarNode = findChildByName(self.node, "TOP/airship_radar_frame");
    local scrapNode  = findChildByName(self.node, "TOP/scrap_frame");
    local fightAbilityNode = findChildByName(self.node, "TOP/fight_ability_frame");
    local statueNode = findChildByName(self.node, "TOP/statue_frame");
    local airShipAttribNode2 = findChildByName(self.node, "TOP/airship_attrib_frame2");
    local activityTimesNode = findChildByName(self.node, "TOP/activity_times_frame");
    local manualNode = findChildByName(self.node, "TOP/engineering_manual_frame");
    local rotineNode = findChildByName(self.node, "TOP/rotine_activity_frame");
    local fateLinkNode = findChildByName(self.node, "TOP/fate_link_frame");

    local allFrameNode = { lifeNode, fruitNode, workerNode, gemNode, heroNode, feedNode,
        airShipAttribNode, airshipRadarNode, scrapNode, fightAbilityNode, statueNode,
        airShipAttribNode2, activityTimesNode, manualNode, rotineNode, fateLinkNode, };

    self.allFrameNode = allFrameNode;

    -- 记录第一栏各个节点
    local treeNode   = findChildByName(self.node, "TOP/tree_frame");
    local moneyNode  = findChildByName(self.node, "TOP/money_frame");
    local spNode     = findChildByName(self.node, "TOP/sp_frame");
    local copperNode = findChildByName(self.node, "TOP/copper_frame");
    local airShipScoreNode = findChildByName(self.node, "TOP/airship_score_frame");
    local firstScrapNode  = findChildByName(self.node, "TOP/first_scrap_frame");
    local relicFragmentNode  = findChildByName(self.node, "TOP/relic_fragment_frame");
    local ladaduomuNode = findChildByName(self.node, "TOP/ladaduomu_coin_frame");
    local activityDataNode = findChildByName(self.node, "TOP/activity_data_frame");
    local activityExchangeNode = findChildByName(self.node, "TOP/activity_exchange_frame");
    local fateChainNode = findChildByName(self.node, "TOP/fate_chain_frame");

    local topFrameNode = {treeNode, moneyNode, spNode, copperNode, airShipScoreNode, firstScrapNode,
        relicFragmentNode, ladaduomuNode, activityDataNode, activityExchangeNode, fateChainNode, };
    self.topFrameNode = topFrameNode;

    local headNode = findChildByName(self.node, "TOP/frame");
    local airShipNode = findChildByName(self.node, "TOP/airship_frame");
    local btnSysSet = findChildByName(self.node, "TOP/set_btn");
    local sysSetPanel = findChildByName(self.node, "TOP/set_btn_panel");
    self.oldHeadPos = cc.p(headNode:getPosition());
    self.oldAirShipPos = cc.p(airShipNode:getPosition());
    self.oldMoneyPos = cc.p(moneyNode:getPosition());
    self.oldWokerBarPos = cc.p(workerNode:getPosition());
    self.oldSysSetPos = cc.p(btnSysSet:getPosition());
    self.oldSysSetPanelPos = cc.p(sysSetPanel:getPosition());
    self.oldAirShipScorePos = cc.p(airShipScoreNode:getPosition());
    self.oldAirShipAttribPos = cc.p(airShipAttribNode:getPosition());
    self.oldAirShipRadarPos = cc.p(airshipRadarNode:getPosition());

    local pauseStateLabel = findChildByName(self.node, "TOP/life_frame/pause_state");
    TextStyleM.setTextStyle(pauseStateLabel, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    pauseStateLabel:setString(getLocStr("in_pause_state"));

    local moneyLabel = findChildByName(self.node, "TOP/money_frame/money_text");
    self:setTopMenuTextStyle(moneyLabel);
    -- 记录下金币节点的初始锚点和初始坐标
    self.initMoneyNodeAnchor = cc.p(moneyLabel:getAnchorPoint());
    self.initMoneyNodePos = cc.p(moneyLabel:getPosition());


    -- 重绘英雄头像
    self:redrawHeadIcon();

    -- 默认显示体力条
    self:showTreeInfo();
    self:showLifeInfo();

    self:resize();

    self.feedPetClassId = nil;

    -- 在迷宫内限制操作
    if DungeonM.isInDungeon() then
        self:checkInDungeonState();
    end
end

-- 注册事件处理回调函数
function UITopMenu:registerEventCallback()

    -- 玩家经验增加
    EventMgr.register("UITopMenu", event.USER_EXP_UP, function()
        self:updateTreeInfo();
    end);

    -- 宠物加载完成
    EventMgr.register("UITopMenu", event.LOAD_PET_OK, function()
        -- 重绘英雄头像
        self:redrawHeadIcon();
    end);

    -- 注册玩家信息更新的回调
    EventMgr.register("UITopMenu", event.USER_INFO_UPDATED, function(args)
        if not self:isVisible() then
            -- print("UITopMenu不可见，无需处理, desc:"..args)
            return;
        end

        self:updateProps();

        -- 如果是飞艇，那么更新下显示
        if args == "new_airships" then
            self:updateNewAirShipInfo();
            self:updateNewFragment();
            self:updateAirShipAttrib();
        end

        -- 如果是天空活动数据，那么更新下显示
        if args == "sky_activity" then
            self:updateActivityData();
            self:updateActivityTimes();
            self:updateActivityTimesRecoverTime();
        end

        -- 常规活动
        if args == "rotine_activity_info" then
            self:updateRotineActivity();
        end
    end);

    -- 注册浮岛信息更新的回调
    EventMgr.register("UITopMenu", event.SKY_CITY_EXPLORE, function()
        self:updateAirShipRadar();
    end);

    -- 注册英雄出战的事件
    EventMgr.register("UITopMenu", event.ACTIVE_PET, function(classId)
        self:redrawHeadIcon();
    end);

    -- 关注服务器状态更新事件
    EventMgr.register("UITopMenu", event.SERVER_STATUS_UPDATE, function(para)
        self:redrawHeadIcon();
    end);

    -- 注册英雄穿上时装的回调
    EventMgr.register("UITopMenu", event.EQUIP, function(args)
        local type = EquipM.query(args, "type");
        if type == EQUIP_TYPE_COSTUME then
            self:redrawHeadIcon();
        end
    end);

    -- 注册英雄穿上时装的回调
    EventMgr.register("UITopMenu", event.UNEQUIP, function(args)
        local type = args.type;
        if type == EQUIP_TYPE_COSTUME then
            self:redrawHeadIcon();
        end
    end);

    -- 注册玩家升级的事件
    EventMgr.register("UITopMenu", event.USER_LEVEL_UP, function(args)
        self:whenUserLevelUp(args);
    end);

    -- 注册喂食英雄改变的事件
    EventMgr.register("UITopMenu", event.FEED_PET_SHOW_CHANGE, function(classId)
        if not classId then
            return;
        end

        self.feedPetClassId = classId;

        self:showFeedInfo();
    end);

    -- 活力恢复剩余时间回调
    EventMgr.register("UITopMenu", event.RECOVERY_LEFT_TIME, function()
        if self:isVisible() then
            self:updateLifeLeftTime();
        end
    end);

    -- 恢复剩余时间回调
    EventMgr.register("UITopMenu", event.FATE_LINK_LEFT_TIME, function()
        if self:isVisible() then
            self:updateFateLinkLeftTime();
        end
    end);

    -- 关注物品数量变化
    EventMgr.register("UITopMenu", event.ITEM_COUNT_UPDATED, function(classId)
        if classId == ITEM_ID_COPPER then
            self:updateCopperInfo();
        elseif classId == ITEM_ID_RELIC then
            self:updateScrapInfo();
        elseif classId == ITEM_ID_STATUE then
            self:updateStatueInfo();
        elseif classId == ITEM_ID_GEAR then
            self:updateGearInfo();
        elseif table.indexOf(SkyActivityM.getSkyAcitivityMedalList(), classId) >= 1 then
            self:updateActivityData();
        elseif classId == exchangeCurrency then
            self:updateActivityExchangeInfo();
        end
    end);

    -- 关注探索点变化以重绘
    ME.user.dbase:registerCb("UITopMenu", { "search_point", }, function()
        self:updateSpInfo();
    end);

    -- 关注出战的飞船变化以重绘
    ME.user.dbase:registerCb("UITopMenu", { "active_airship", }, function()
        self:showAirShipAttrib2();
        self:updateAirShipAttrib();

        self:redrawAirShipFrame();
        self:playAirShipEffect("airship");
    end);

    -- 关注新版飞船变化以重绘
    ME.user.dbase:registerCb("UITopMenu", { "new_airship", }, function()
        self:showAirShipAttrib2();
        self:updateAirShipAttrib();
    end);

    -- 编组发生变化的回调
    EventMgr.register("UITopMenu", event.SKY_CITY_SAVE_GROUP, function(para)
        self:showAirShipAttrib();
        self:updateAirShipAttrib();

        self:showAirShipScore();
    end);

    -- 冈布奥觉醒雕像建造完毕的回调
    EventMgr.register("UITopMenu", event.AWAKE_CARVING_FINISH, function(para)
        self:showAirShipAttrib();
        self:updateAirShipAttrib();

        self:showAirShipScore();
    end);

    -- 天空之城编组出战
    EventMgr.register("UITopMenu", event.SKY_ACTIVE_GROUP, function(para)
        self:showAirShipAttrib();

        self:showAirShipScore();

        self:redrawAirShipFrame();
        self:playAirShipEffect("camp");
    end);

    -- 关注链接成功
    EventMgr.register("UITopMenu", event.FATE_CHAIN_SUCCESS, function(para)
        self:updateFateChainInfo();
    end);

    -- 关注MSG_IN_DUNGEON消息回调
    MSG.registerMsgTrigger("UITopMenu", "MSG_IN_DUNGEON", function(para)
        self:checkInDungeonState();
    end);

    self:updateLifeLeftTime();
    self:updateFateLinkLeftTime();

    -- 界面析构后，需要清理下
    self:registerScriptHandler(function(eventType)
        if eventType == "exit" then
            cclog("UITopMenu 界面析构清理");
            EventMgr.removeAll("UITopMenu");
            ME.user.dbase:removeCb("UITopMenu", { "search_point", });
        end
    end);
end

-- 注册点击事件
function UITopMenu:registerTouchEvent()
    -- 注册系统设置按钮点击事件
    local btnSysSet = findChildByName(self.node, "TOP/set_btn");
    local function onSetClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_set");
            local uiSetting = UISystemSetting.create();
            UIMgr:getCurrentScene():addForm(uiSetting);

            -- print(Profiler.getPrintMsg());
        end
    end
    btnSysSet:addTouchEventListener(onSetClick);

    local airShipScoreNode = findChildByName(self.node, "TOP/airship_score_frame");
    local airShipAttribNode = findChildByName(self.node, "TOP/airship_attrib_frame");

    local function onAirShipFrameClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            -- 说明界面
            require  "game/ui/form/sky_city/UIAirShipSkillExplain";

            if UIMgr.getCurrentScene():getFormByName("UIAirShipSkillExplain") then
                return;
            end

            local title = getLocStr("airship_combat_title");
            local desc = getLocStr("airship_combat_desc");

            local extraDesc = {
                ["title"] = getLocStr("airship_debuff_title");
                ["desc"] = getLocStr("airship_debuff_desc");
            }

            -- 复用秘宝说明
            local uiForm = UIAirShipSkillExplain.create(title, desc, nil, nil, extraDesc);
            UIMgr.getCurrentScene():addForm(uiForm);
        end
    end
    airShipScoreNode:addTouchEventListener(onAirShipFrameClick);
    airShipAttribNode:addTouchEventListener(onAirShipFrameClick);
end

-- 更新属性信息
function UITopMenu:updateProps()
    -- 更新金币信息
    local moneyLabel = findChildByName(self.node, "TOP/money_frame/money_text");
    local money = ME.user.dbase:query("money", 0);
    moneyLabel:setString(tostring(money));

    local lifeNode = findChildByName(self.node, "TOP/life_frame");

    if lifeNode:isVisible() then
        -- 显示体力图标
        local maxLife = ME.user:getMaxLife();
        local curLife = ME.user.dbase:query("life", 0);
        for i = 1, 9 do
            local iconImage = findChildByName(lifeNode, "life"..i);
            iconImage:loadTexture(getSmallAttribIconPath("radish"));
            if i <= curLife then
                -- 亮着
                iconImage:setVisible(true);
            elseif i <= maxLife then
                -- 灰色
                iconImage:setVisible(true);
                iconImage.grayMode = false;
                setGrayMode(iconImage, true);
            else
                -- 不可见
                iconImage:setVisible(false);
            end
        end

        if curLife > maxLife then
            for i = maxLife + 1, curLife do
                local iconImage = findChildByName(lifeNode, "life"..i);
                if iconImage then
                    iconImage:loadTexture(getSmallAttribIconPath("radish"));
                    iconImage:setVisible(true);
                end
            end
        end
    end

    local fateLinkNode = findChildByName(self.node, "TOP/fate_link_frame");
    if fateLinkNode:isVisible() then
        -- 显示链接图标
        local maxLink = FateChainM.getMaxLinkTimes();
        local curLink = ME.user.dbase:query("fate_link", 0);
        for i = 1, maxLink do
            local iconImage = findChildByName(fateLinkNode, "link"..i);
            iconImage:loadTexture(getSmallAttribIconPath("fate_link"));
            if i <= curLink then
                -- 亮着
                iconImage:setVisible(true);
            else
                -- 灰色
                iconImage:setVisible(true);
                iconImage.grayMode = false;
                setGrayMode(iconImage, true);
            end
        end
    end

    -- 更新钻石信息
    self:updateGemInfo();

    -- 更新飞艇雷达信息
    self:updateAirShipRadar();
end

-- 显示金币信息
function UITopMenu:showMoneyInfo()
    local moneyNode = findChildByName(self.node, "TOP/money_frame");
    self:setTopFrameNodeVisible(moneyNode);
end

-- 获取英雄节点
function UITopMenu:getHeroNode()
    local headImg = findChildByName(self.node, "TOP/frame/head_pic");
    return headImg;
end

-- 获取体力节点
function UITopMenu:getLifeNode(index)
    local lifeNode = findChildByName(self.node, "TOP/life_frame");
    return findChildByName(lifeNode, "life"..index);
end

-- 获取链接节点
function UITopMenu:getFateLifeNode(index)
    local linkNode = findChildByName(self.node, "TOP/fate_link_frame");
    return findChildByName(linkNode, "link"..index);
end

-- 获取金币图标节点
function UITopMenu:getMoneyIconNode()
    local moneyIconNode = findChildByName(self.node, "TOP/money_frame/money_bg");
    return moneyIconNode;
end

-- 获取金币文本节点
function UITopMenu:getMoneyTextNode()
    local moneyTextNode = findChildByName(self.node, "TOP/money_frame/money_text");
    return moneyTextNode;
end

-- 获取金币节点初始锚点
function UITopMenu:getMoneyTextNodeAnchorPoint()
    return self.initMoneyNodeAnchor;
end

-- 获取金币节点初始坐标
function UITopMenu:getMoneyTextNodePos()
    return self.initMoneyNodePos;
end

-- 居中显示金币条，其他隐藏，从右边飞入
function UITopMenu:moneyBarFlyIn()
    local moneyNode = findChildByName(self.node, "TOP/money_frame");
    local oldPosX = moneyNode:getPositionX();

    self:showMoneyBar();
    local duration = 0.3;

    local moneyNode = findChildByName(self.node, "TOP/money_frame");
    moneyNode:setPositionX(DESIGN_WIDTH);
    local moveTo = cc.MoveTo:create(duration, cc.p(0, moneyNode:getPositionY()));
    moneyNode:runAction(moveTo);

    local btnSysSet = findChildByName(self.node, "TOP/set_btn");
    local oldPosX1 = btnSysSet:getPositionX();
    btnSysSet:setPositionX(oldPosX1 + DESIGN_WIDTH);
    btnSysSet:runAction(cc.MoveTo:create(duration, cc.p(oldPosX1, btnSysSet:getPositionY())));

    local sysSetPanel = findChildByName(self.node, "TOP/set_btn_panel");
    local oldPosX2 = sysSetPanel:getPositionX();
    sysSetPanel:setPositionX(oldPosX2 + DESIGN_WIDTH);
    sysSetPanel:runAction(cc.MoveTo:create(duration, cc.p(oldPosX2, sysSetPanel:getPositionY())));
end

-- 居中显示金币条，其他隐藏
function UITopMenu:showMoneyBar()
    self:setVisible(true);

    local panel = findChildByName(self.node, "TOP");
    panel:stopAllActions();
    panel:setPositionY(AlignM.frameSize.height);

    -- 头像隐藏
    local frame = findChildByName(self.node, "TOP/frame");
    frame:setVisible(false);
    local airShipFrame = findChildByName(self.node, "TOP/airship_frame");
    airShipFrame:setVisible(false);

    -- 金币条显示
    local moneyNode = findChildByName(self.node, "TOP/money_frame");
    self:setTopFrameNodeVisible(moneyNode);

    local oldPosX = moneyNode:getPositionX();
    moneyNode:setPositionX(0);

    local btnSysSet = findChildByName(self.node, "TOP/set_btn");
    btnSysSet:setPositionX(btnSysSet:getPositionX() - oldPosX);
    local sysSetPanel = findChildByName(self.node, "TOP/set_btn_panel");
    sysSetPanel:setPositionX(sysSetPanel:getPositionX() - oldPosX);

    -- 底下全部隐藏
    self:setFrameNodeVisible(nil);
end

-- 居中显示金币条和工人条，其他隐藏
function UITopMenu:showMoneyBarAndWorkerBar()
    self:showMoneyBar();

    -- 工人条显示
    local workerNode = findChildByName(self.node, "TOP/worker_frame");
    self:setFrameNodeVisible(workerNode);

    workerNode:setPositionX(0);
end

-- 显示工人条，从右边飞入
function UITopMenu:workerBarFlyIn()
    self:showMoneyBarAndWorkerBar();

    local duration = 0.3;

    local workerNode = findChildByName(self.node, "TOP/worker_frame");
    workerNode:setPositionX(DESIGN_WIDTH);
    local moveTo = cc.MoveTo:create(duration, cc.p(0, workerNode:getPositionY()));
    workerNode:runAction(moveTo);
end

-- 显示人物头像，此时右边只有金币条和工人条
function UITopMenu:headFlyIn()
    local frame = findChildByName(self.node, "TOP/frame");
    frame:setVisible(true);

    local offsetX = 69.28;
    local duration = 0.12;

    local oldPositionX = frame:getPositionX();
    local toPosX = oldPositionX - offsetX;
    frame:setPositionX( toPosX - 200);
    frame:setOpacity(0);
    local fadeIn = cc.FadeIn:create(duration);
    local moveTo = cc.MoveTo:create(duration, cc.p(toPosX, frame:getPositionY()));
    frame:runAction(cc.Spawn:create(fadeIn, moveTo));

    local moneyNode = findChildByName(self.node, "TOP/money_frame");
    local workerNode = findChildByName(self.node, "TOP/worker_frame");
    local btnSysSet = findChildByName(self.node, "TOP/set_btn");
    local sysSetPanel = findChildByName(self.node, "TOP/set_btn_panel");

    -- 0.5秒后整体右弹后左弹
    local function delay()
        local moveRight = cc.MoveBy:create(duration, cc.p(offsetX + 100, 0));
        local moveLeft = cc.MoveBy:create(duration, cc.p(-100, 0));
        local moveRight2 = cc.MoveBy:create(duration, cc.p(30, 0));
        local moveLeft2 = cc.MoveBy:create(duration, cc.p(-30, 0));
        local moveRight3 = cc.MoveBy:create(duration, cc.p(10, 0));
        local moveLeft3 = cc.MoveBy:create(duration, cc.p(-10, 0));
        local moveRight4 = cc.MoveBy:create(duration, cc.p(3, 0));
        local moveLeft4 = cc.MoveBy:create(duration, cc.p(-3, 0));
        local action = cc.Sequence:create(moveRight, moveLeft, moveRight2, moveLeft2, moveRight3, moveLeft3, moveRight4, moveLeft4);
        moneyNode:runAction(action);
        workerNode:runAction(action:clone());
        btnSysSet:runAction(action:clone());
        sysSetPanel:runAction(action:clone());

        local frameMoveRight = cc.MoveBy:create(duration, cc.p(offsetX + 40, 0));
        local frameMoveLeft = cc.MoveBy:create(duration, cc.p(-40, 0));
        local frameMoveRight2 = cc.MoveBy:create(duration, cc.p(10, 0));
        local frameMoveLeft2 = cc.MoveBy:create(duration, cc.p(-10, 0));
        local action2 = cc.Sequence:create(frameMoveRight, frameMoveLeft, frameMoveRight2, frameMoveLeft2);
        frame:runAction(action2);
    end
    performWithDelay(self, delay, duration);
end

-- 重置金币条各个位置
function UITopMenu:resetBars()
    local headNode = findChildByName(self.node, "TOP/frame");
    local airShipNode = findChildByName(self.node, "TOP/airship_frame");
    local moneyNode = findChildByName(self.node, "TOP/money_frame");
    local workerNode = findChildByName(self.node, "TOP/worker_frame");
    local btnSysSet = findChildByName(self.node, "TOP/set_btn");
    local sysSetPanel = findChildByName(self.node, "TOP/set_btn_panel");
    local airShipScoreNode = findChildByName(self.node, "TOP/airship_score_frame");
    local airShipAttribNode = findChildByName(self.node, "TOP/airship_attrib_frame");
    local airshipRadarNode = findChildByName(self.node, "TOP/airship_radar_frame");

    headNode:setVisible(true);
    headNode:setPosition(self.oldHeadPos);
    airShipNode:setPosition(self.oldAirShipPos);
    moneyNode:setPosition(self.oldMoneyPos);
    workerNode:setPosition(self.oldWokerBarPos);
    btnSysSet:setPosition(self.oldSysSetPos);
    sysSetPanel:setPosition(self.oldSysSetPanelPos);
    airShipScoreNode:setPosition(self.oldAirShipScorePos);
    airShipAttribNode:setPosition(self.oldAirShipAttribPos);
    airshipRadarNode:setPosition(self.oldAirShipRadarPos);
end

-- 显示世界树信息
function UITopMenu:showTreeInfo()
    local treeNode = findChildByName(self.node, "TOP/tree_frame");
    self:setTopFrameNodeVisible(treeNode);

    self:updateTreeInfo();
end

function UITopMenu:updateTreeInfo()
    -- 世界树等级
    local level = ME.user:getLevel();
    local levelStr = string.format(getLocStr("talent_level_format"), level);
    local treeLevelText = findChildByName(self.node, "TOP/tree_frame/tree_level_text");
    self:setTopMenuTextStyle(treeLevelText);
    treeLevelText:setString(levelStr);

    -- 世界树经验
    local treeExpTip = findChildByName(self.node, "TOP/tree_frame/tree_exp_tip");
    self:setTopMenuTextStyle(treeExpTip);
    treeExpTip:setString(getLocStr("tree_exp"));

    self.curExp = ME.user:getExp();
    self.curLevel = ME.user:getLevel();
    self.curMaxExp = UserM.queryWorldTree(self.curLevel, "exp");
    local treeExpText = findChildByName(self.node, "TOP/tree_frame/tree_exp_text");
    local percent = self.curExp / self.curMaxExp * 100;
    percent = string.format("%d", math.floor(percent));
    local text = percent .. "%";
    self:setTopMenuTextStyle(treeExpText);
    treeExpText:setString(text);

end

-- 显示探索点信息
function UITopMenu:showSpInfo()
    local spNode   = findChildByName(self.node, "TOP/sp_frame");
    self:setTopFrameNodeVisible(spNode);

    self:updateSpInfo();
end

-- 更新探索点信息
function UITopMenu:updateSpInfo()
    local spNode   = findChildByName(self.node, "TOP/sp_frame");
    local spAmount = ME.user:queryAttrib("search_point");
    local amountLabel = findChildByName(spNode, "count");
    self:setTopMenuTextStyle(amountLabel);
    amountLabel:setString(tostring(spAmount));
end

-- 显示齿轮信息
function UITopMenu:showGearInfo()
    local gearNode = findChildByName(self.node, "TOP/copper_frame");
    self:setTopFrameNodeVisible(gearNode);

    -- 更新齿轮信息
    self:updateGearInfo();
end

-- 更新齿轮信息
function UITopMenu:updateGearInfo()
    -- 齿轮
    local gearNode = findChildByName(self.node, "TOP/copper_frame");
    -- 图标
    local bg = findChildByName(gearNode, "bg");
    local fileName = ItemM.query(ITEM_ID_GEAR, "icon");
    bg:loadTexture(getItemIconPath(fileName));

    -- 数量
    local gearAmount = ItemM.getAmount(ME.user, ITEM_ID_GEAR);
    local amountLabel = findChildByName(gearNode, "count");
    self:setTopMenuTextStyle(amountLabel);
    amountLabel:setString(tostring(gearAmount));
end

-- 显示折弯的铜币信息
function UITopMenu:showCopperInfo()
    local copperNode = findChildByName(self.node, "TOP/copper_frame");
    self:setTopFrameNodeVisible(copperNode);

    -- 更新折弯铜币信息
    self:updateCopperInfo();
end

-- 更新折弯铜币信息
function UITopMenu:updateCopperInfo()
    -- 折弯的铜币
    local copperNode = findChildByName(self.node, "TOP/copper_frame");
    -- 图标
    local bg = findChildByName(copperNode, "bg");
    local fileName = ItemM.query(ITEM_ID_COPPER, "icon");
    bg:loadTexture(getItemIconPath(fileName));

    -- 数量
    local copperAmount = ItemM.getAmount(ME.user, ITEM_ID_COPPER);
    local amountLabel = findChildByName(copperNode, "count");
    self:setTopMenuTextStyle(amountLabel);
    amountLabel:setString(tostring(copperAmount));
end

function UITopMenu:setTopFrameNodeVisible(curShowNode)
    for _, node in pairs(self.topFrameNode) do
        if curShowNode ~= nil and node:getName() == curShowNode:getName() then
            node:setVisible(true);
        else
            node:setVisible(false);
        end
    end
end

-- 更新工坊信息
function UITopMenu:updateWorkerInfo(total, idle)
    local leftCountLabel = findChildByName(self.node, "TOP/worker_frame/left_count");

    local idleWorkerNum = idle or AlchemyWorkshopM.getIdleWorkerNum();
    local totalWorkerNum = total or AlchemyWorkshopM.getTotalWorkerNum()
    self:setTopMenuTextStyle(leftCountLabel);
    leftCountLabel:setString(tostring(totalWorkerNum - idleWorkerNum).."/"..totalWorkerNum);

    local idleWorkerNumLabel = findChildByName(self.node, "TOP/worker_frame/idle_text");
    idleWorkerNumLabel = replaceTextNode(idleWorkerNumLabel);

    if idleWorkerNum > 0 then
        self:setTopMenuTextStyle2(idleWorkerNumLabel);
        idleWorkerNumLabel:setString(string.format(getLocStr("idle_woker_num"), idleWorkerNum));
        idleWorkerNumLabel:setVisible(true);
    else
        idleWorkerNumLabel:setVisible(false);
    end

    -- 有空闲的工人，字体跳动提醒
    self.node:stopAllActions();
    setJumpStop("idleWorkerNumLabel", true);
    if idleWorkerNum > 0 then
        local nameCount = string.getWCharCount(idleWorkerNumLabel:getString());
        setTextJump(nameCount, idleWorkerNumLabel, self.node, "idleWorkerNumLabel");
    end
end

-- 显示工坊信息
function UITopMenu:showWorkerInfo(total, idle)
    local workerNode = findChildByName(self.node, "TOP/worker_frame");
    self:setFrameNodeVisible(workerNode);

    self:updateWorkerInfo(total, idle);
end

-- 显示体力信息
function UITopMenu:showLifeInfo()
    local lifeNode = findChildByName(self.node, "TOP/life_frame");
    self:setFrameNodeVisible(lifeNode);

    self:updateProps();

    self:startCountingDown();

    self:checkPauseState();
end

-- 显示喂食信息
function UITopMenu:showFeedInfo()
    local feedNode = findChildByName(self.node, "TOP/feed_frame");
    self:setFrameNodeVisible(feedNode);

    -- 获取当前出战英雄
    if not self.feedPetClassId then
        return;
    end

    local activeHero = PetM.getMyPet(self.feedPetClassId);

    if not activeHero then
        activeHero = ME.user:getActivePet();
    end

    if not activeHero then
        return;
    end

    local maxFeedId = PetM.getMaxFeedId(activeHero);

    local curTimes = #activeHero:getFeedRecord();
    local timesLabel = findChildByName(feedNode, "feed_times");
    local timesStr = string.format(getLocStr("feed_times_format"), curTimes, maxFeedId);
    self:setTopMenuTextStyle(timesLabel);
    timesLabel:setString(timesStr);

    -- 显示冈布奥的系别
    local depNameLabel = findChildByName(feedNode, "dep_name");
    local depId = PetM.query(self.feedPetClassId, "department_order")[1];
    local depName = CareerM.getDepartmentName(depId);
    self:setTopMenuTextStyle3(depNameLabel);
    depNameLabel:setString(depName);
end

-- 显示拉达多姆金币信息
function UITopMenu:showLadaduomuCoin()
    local ladaduomuNode = findChildByName(self.node, "TOP/ladaduomu_coin_frame");
    self:setTopFrameNodeVisible(ladaduomuNode);

    -- 更新拉达多姆金币信息
    self:updateLadaduomuCoinInfo();
end

-- 更新拉达多姆金币信息
function UITopMenu:updateLadaduomuCoinInfo()
    local ladaduomuNode = findChildByName(self.node, "TOP/ladaduomu_coin_frame");

    -- 图标
    local bg = findChildByName(ladaduomuNode, "bg");
    local fileName = ItemM.query(ITEM_ID_LADADUOMU_COIN, "icon");
    bg:loadTexture(getItemIconPath(fileName));

    -- 数量
    local amount = ItemM.getAmount(ME.user, ITEM_ID_LADADUOMU_COIN);
    local amountLabel = findChildByName(ladaduomuNode, "count");
    self:setTopMenuTextStyle(amountLabel);
    amountLabel:setString(tostring(amount));
end

-- 显示活动兑换信息
function UITopMenu:showActivityExchange()
    local activityExchangeNode = findChildByName(self.node, "TOP/activity_exchange_frame");
    self:setTopFrameNodeVisible(activityExchangeNode);
    self:updateActivityExchangeInfo();
end

-- 显示活动兑换货币信息
function UITopMenu:updateActivityExchangeInfo()
    local activityExchangeNode = findChildByName(self.node, "TOP/activity_exchange_frame");

    local classId = exchangeCurrency;

    -- 图标
    local bg = findChildByName(activityExchangeNode, "bg");
    local fileName = ItemM.query(classId, "icon");
    bg:loadTexture(getItemIconPath(fileName));

    -- 数量
    local amount = ItemM.getAmount(ME.user, classId);
    local amountLabel = findChildByName(activityExchangeNode, "count");
    self:setTopMenuTextStyle(amountLabel);
    amountLabel:setString(tostring(amount));
end

-- 检查暂离状态
function UITopMenu:checkPauseState()
    local pauseStateLabel = findChildByName(self.node, "TOP/life_frame/pause_state");
    if DungeonM.isInDungeon() and UIMgr.getCurrentScene().isInMainMap
        and UIMgr.getCurrentScene():isInMainMap() then
        -- SLIMEC-3367不显示当前提示
        -- pauseStateLabel:setVisible(true);
        pauseStateLabel:setVisible(false);
    else
        pauseStateLabel:setVisible(false);
    end
end

-- 检查是否在迷宫状态
function UITopMenu:checkInDungeonState()
    local pauseStateLabel = findChildByName(self.node, "TOP/life_frame/pause_state");
    if DungeonM.isInDungeon() then
        pauseStateLabel:setVisible(true);
    else
        pauseStateLabel:setVisible(false);
    end
end

-- 暂离信息隐藏
function UITopMenu:setNormalColor()
    local pauseStateLabel = findChildByName(self.node, "TOP/life_frame/pause_state");
    pauseStateLabel:setVisible(false);
end

-- 更新英雄信息
function UITopMenu:updateHeroInfo()
    local leftCountLabel = findChildByName(self.node, "TOP/hero_frame/hero_count");

    local allHero = PetM.getIllustratePets();
    local allCount = #allHero;

    local heros = table.keys(ME.user.pets);
    local activeCount = #heros;

    self:setTopMenuTextStyle(leftCountLabel);
    leftCountLabel:setString(string.format(getLocStr("unlock_hero"), activeCount, allCount));
end

-- 显示英雄信息
function UITopMenu:showHeroInfo()
    local heroNode = findChildByName(self.node, "TOP/hero_frame");
    self:setFrameNodeVisible(heroNode);

    self:updateHeroInfo();
end

-- 更新世界树果实信息
function UITopMenu:updateFruitInfo()
    local leftCountLabel = findChildByName(self.node, "TOP/fruit_frame/fruit_count");
    local num = ItemM.getAmount(ME.user, 1110);
    self:setTopMenuTextStyle(leftCountLabel);
    leftCountLabel:setString(tostring(num));
end

-- 显示世界树果实信息
function UITopMenu:showFruitInfo()
    local fruitNode = findChildByName(self.node, "TOP/fruit_frame");
    self:setFrameNodeVisible(fruitNode);

    self:updateFruitInfo();
end

-- 显示钻石
function UITopMenu:showGem()
    local gemNode = findChildByName(self.node, "TOP/gem_frame");
    self:setFrameNodeVisible(gemNode);

    local gemImg = findChildByName(gemNode, "gem_icon");
    local icon = FieldsM.query("gem", "icon");

    local gemLabel = findChildByName(gemNode, "gem_text");
    local gemAmount = ME.user:queryAttrib("gem");
    self:setTopMenuTextStyle(gemLabel);
    gemLabel:setString(tostring(gemAmount));
end

-- 显示飞艇总战力
function UITopMenu:showAirShipScore()
    local airShipScoreNode = findChildByName(self.node, "TOP/airship_score_frame");
    self:setTopFrameNodeVisible(airShipScoreNode);

    local countLabel = findChildByName(airShipScoreNode, "count");
    local count = SkyCombatM.calcArmyAbility();
    if UIMgr.getCurrentScene():isOpen("UIRelicUserInfo") then
        local prop = PropM.combine(ME.user, "rob_attrib", "fight_ability");
        count = PropM.apply(prop, count);
    end
    self:setTopMenuTextStyle(countLabel);
    countLabel:setString(tostring(count));
end

-- 显示当前拥有的古遗迹碎片数量
function UITopMenu:showRelicFragment()
    local relicFragmentNode = findChildByName(self.node, "TOP/relic_fragment_frame");
    self:setTopFrameNodeVisible(relicFragmentNode);

    -- 遗迹碎片
    local countLabel = findChildByName(relicFragmentNode, "count");
    local count = ItemM.getAmount(ME.user, ITEM_ID_RELIC);
    self:setTopMenuTextStyle(countLabel);
    countLabel:setString(tostring(count));
end

-- 新版的飞艇属性界面(先保留旧版的接口)
function UITopMenu:showAirShipAttrib2()
    local airShipAttribNode = findChildByName(self.node, "TOP/airship_attrib_frame2");
    self:setFrameNodeVisible(airShipAttribNode);

    local remouldIcon       = findChildByName(airShipAttribNode, "remould");
    local chipIcon          = findChildByName(airShipAttribNode, "airship_fragment");
    local remouldCurLabel = findChildByName(airShipAttribNode, "remould_cur_value");
    local remouldNeedLabel = findChildByName(airShipAttribNode, "remould_need_value");
    local fragmentCurLabel = findChildByName(airShipAttribNode, "fragment_cur_value");
    local fragmentNeedLabel = findChildByName(airShipAttribNode, "fragment_need_value");

    self:setTopMenuTextStyle(remouldCurLabel);
    self:setTopMenuTextStyle(remouldNeedLabel);
    self:setTopMenuTextStyle(fragmentCurLabel);
    self:setTopMenuTextStyle(fragmentNeedLabel);

    -- 获取当前界面选中的飞艇id
    local shipId = NewAirShipM.getSelectedAirShip();
    local curRemouldValue = NewAirShipM.getAirShipStrengtenTimes(shipId);
    local needRemouldValue = NewAirShipM.getCurMaxStrengthenLevel(shipId);

    remouldCurLabel:setString(curRemouldValue);
    remouldNeedLabel:setString("/" .. needRemouldValue);
    local digit = calcDigit(curRemouldValue);
    local offset1 = remouldCurLabel:getVirtualRenderer():getContentSize().width + 4*digit;
    remouldNeedLabel:setPositionX(remouldCurLabel:getPositionX() + offset1);

    local chipId = NewAirShipM.query(shipId, "chip_id");
    local cost;
    if NewAirShipM.hasOwnShip(shipId) then
        cost = FormulaM.invoke("CALC_AIRSHIP_UPGRADE_COST", shipId, NewAirShipM.getAirShipRank(shipId));
    else
        cost = NewAirShipM.query(shipId, "cost");
    end
    local curChipValue = ItemM.getAmount(ME.user, chipId);
    local needChipValue;
    local maxRank = NewAirShipM.getMaxRank(shipId);
    if NewAirShipM.getAirShipRank(shipId) == maxRank then
        needChipValue = "-";
    else
        needChipValue = cost and cost[chipId] or 0;
    end

    fragmentCurLabel:setString(curChipValue);
    fragmentNeedLabel:setString("/" .. needChipValue);
    digit = calcDigit(curChipValue);
    local offset2 = fragmentCurLabel:getVirtualRenderer():getContentSize().width + 4*digit;
    fragmentNeedLabel:setPositionX(fragmentCurLabel:getPositionX() + offset2);

    -- 设置芯片的图标
    local iconId = ItemM.query(chipId, "icon");
    chipIcon:loadTexture(getItemIconPath(iconId));
    chipIcon:setScale(0.44);
end

-- 刷新顶栏的新版的飞艇信息
function UITopMenu:updateNewAirShipInfo()
    local airShipAttribNode = findChildByName(self.node, "TOP/airship_attrib_frame2");
    local remouldIcon       = findChildByName(airShipAttribNode, "remould");
    local chipIcon          = findChildByName(airShipAttribNode, "airship_fragment");
    local remouldCurLabel   = findChildByName(airShipAttribNode, "remould_cur_value");
    local remouldNeedLabel  = findChildByName(airShipAttribNode, "remould_need_value");
    local fragmentCurLabel  = findChildByName(airShipAttribNode, "fragment_cur_value");
    local fragmentNeedLabel = findChildByName(airShipAttribNode, "fragment_need_value");

    -- 获取当前界面选中的飞艇id
    local shipId = NewAirShipM.getSelectedAirShip();
    local chipId = NewAirShipM.query(shipId, "chip_id");

    -- 获取当前界面选中的飞艇id
    local curRemouldValue = NewAirShipM.getAirShipStrengtenTimes(shipId);
    local needRemouldValue = NewAirShipM.getCurMaxStrengthenLevel(shipId);

    remouldCurLabel:setString(curRemouldValue);
    remouldNeedLabel:setString("/" .. needRemouldValue);
    local digit = calcDigit(curRemouldValue);
    local offset1 = remouldCurLabel:getVirtualRenderer():getContentSize().width + 4*digit;
    remouldNeedLabel:setPositionX(remouldCurLabel:getPositionX() + offset1);

    local cost;
    if NewAirShipM.hasOwnShip(shipId) then
        cost = FormulaM.invoke("CALC_AIRSHIP_UPGRADE_COST", shipId, NewAirShipM.getAirShipRank(shipId));
    else
        cost = NewAirShipM.query(shipId, "cost");
    end
    local curChipValue = ItemM.getAmount(ME.user, chipId);
    local needChipValue;
    local maxRank = NewAirShipM.getMaxRank(shipId);
    if NewAirShipM.getAirShipRank(shipId) == maxRank then
        needChipValue = "-";
    else
        needChipValue = cost and cost[chipId] or 0;
    end


    fragmentCurLabel:setString(curChipValue);
    fragmentNeedLabel:setString("/" .. needChipValue);
    digit = calcDigit(curChipValue);
    local offset2 = fragmentCurLabel:getVirtualRenderer():getContentSize().width + 4*digit;
    fragmentNeedLabel:setPositionX(fragmentCurLabel:getPositionX() + offset2);

    -- 设置芯片的图标
    local iconId = ItemM.query(chipId, "icon");
    chipIcon:loadTexture(getItemIconPath(iconId));
    chipIcon:setScale(0.44);
end

-- 刷新顶栏新版飞艇的遗迹碎片数量
function UITopMenu:updateNewFragment()
    local relicFragmentNode = findChildByName(self.node, "TOP/relic_fragment_frame");
    local countLabel = findChildByName(relicFragmentNode, "count");

    local count = ItemM.getAmount(ME.user, ITEM_ID_RELIC);
    countLabel:setString(tostring(count));
end

-- 显示飞艇属性
function UITopMenu:showAirShipAttrib()
    local airShipAttribNode = findChildByName(self.node, "TOP/airship_attrib_frame");
    self:setFrameNodeVisible(airShipAttribNode);

    local fireLabel     = findChildByName(airShipAttribNode, "fire_value");
    local armorLabel    = findChildByName(airShipAttribNode, "armor_value");
    local speedLabel    = findChildByName(airShipAttribNode, "speed_value");
    local luckLabel     = findChildByName(airShipAttribNode, "luck_value");

    self:setTopMenuTextStyle(fireLabel);
    self:setTopMenuTextStyle(armorLabel);
    self:setTopMenuTextStyle(speedLabel);
    self:setTopMenuTextStyle(luckLabel);

    local activedShip = NewAirShipM.getActiveAirShip();
    local shipInfo = table.deepcopy(NewAirShipM.getUserAirShipInfo(activedShip));
    if UIMgr.getCurrentScene():isOpen("UIRelicUserInfo") then
        -- or UIMgr.getCurrentScene():isOpen("UIRevengeUserInfo") then
        -- 掠夺或复仇界面中，将掠夺属性加成计算进去
        local attribs = {"fire", "luck", "speed", "armor"};
        for _, attrib in pairs(attribs) do
            -- 防守属性影响
            if shipInfo[attrib] then
                local prop = PropM.combine(ME.user, "rob_attrib", attrib);
                shipInfo[attrib] = PropM.apply(prop, shipInfo[attrib]);
            end
        end
    end

    fireLabel:setString(tostring(shipInfo["fire"] or 0));
    armorLabel:setString(tostring(shipInfo["armor"] or 0));
    speedLabel:setString(tostring(shipInfo["speed"] or 0));
    luckLabel:setString(tostring(shipInfo["luck"] or 0));
end

-- 更新飞船战力
function UITopMenu:updateAirShipScore()
    local airShipScoreNode = findChildByName(self.node, "TOP/airship_score_frame");
    local countLabel = findChildByName(airShipScoreNode, "count");

    local uiGroup = UIMgr.getCurrentScene():getFormByName("UISkyCityGroup");
    local groupId;

    if uiGroup then
        groupId = uiGroup:getSelectGroup();
    end

    local count = SkyCombatM.calcArmyAbility(groupId);
    if UIMgr.getCurrentScene():isOpen("UIRelicUserInfo")
        or UIMgr.getCurrentScene():isOpen("UIRevengeUserInfo") then
        local prop = PropM.combine(ME.user, "rob_attrib", "fight_ability");
        count = PropM.apply(prop, count);
    end
    countLabel:setString(tostring(count));
end


-- 更新飞船属性
function UITopMenu:updateAirShipAttrib()
    local airShipAttribNode = findChildByName(self.node, "TOP/airship_attrib_frame");

    local fireLabel     = findChildByName(airShipAttribNode, "fire_value");
    local armorLabel    = findChildByName(airShipAttribNode, "armor_value");
    local speedLabel    = findChildByName(airShipAttribNode, "speed_value");
    local luckLabel     = findChildByName(airShipAttribNode, "luck_value");

    local groupId;
    local petList;
    local robatList;
    local uiGroup = UIMgr.getCurrentScene():getFormByName("UISkyCityGroup");

    if uiGroup then
        groupId = uiGroup:getSelectGroup();
        petList = SkyCombatM.getGroup(groupId);
        robatList = SkyRobotM.getRobotsByCamp(groupId);
    end

    local activedShip   = NewAirShipM.getActiveAirShip();
    local shipInfo      = table.deepcopy(NewAirShipM.getUserAirShipInfo(activedShip, petList, robatList, groupId));
    if UIMgr.getCurrentScene():isOpen("UIRelicUserInfo")
        or UIMgr.getCurrentScene():isOpen("UIRevengeUserInfo") then
        -- 掠夺或复仇界面中，将掠夺属性加成计算进去
        local attribs = {"fire", "luck", "speed", "armor"};
        for _, attrib in pairs(attribs) do
            -- 防守属性影响
            if shipInfo[attrib] then
                local prop = PropM.combine(ME.user, "rob_attrib", attrib);
                shipInfo[attrib] = PropM.apply(prop, shipInfo[attrib]);
            end
        end
    end

    fireLabel:setString(tostring(shipInfo["fire"]));
    armorLabel:setString(tostring(shipInfo["armor"]));
    speedLabel:setString(tostring(shipInfo["speed"]));
    luckLabel:setString(tostring(shipInfo["luck"]));
end

-- 更新飞船改造次数以及芯片数量
function updateRemouldAndFragment()
    local airShipAttribNode = findChildByName(self.node, "TOP/airship_attrib_frame2");
    local remouldLabel = findChildByName(airShipAttribNode, "remould_value");
    local fragmentLabel = findChildByName(airShipAttribNode, "fragment_value");

   -- self:setTopMenuTextStyle(remouldLabel);
   -- self:setTopMenuTextStyle(fragmentLabel);

    remouldLabel:setString(NewAirShipM.getAirShipStrengtenTimes());
    fragmentLabel:setString();
end

-- 显示雷达信息
function UITopMenu:showAirShipRadar()
    local radarNode = findChildByName(self.node, "TOP/airship_radar_frame");
    self:setFrameNodeVisible(radarNode);

    self:updateAirShipRadar();
end

-- 显示遗迹碎片
function UITopMenu:showRuinsScrap(firstFrame)

    local scrapNode;
    if true == firstFrame then
        scrapNode = findChildByName(self.node, "TOP/first_scrap_frame");
        self:setTopFrameNodeVisible(scrapNode);
    else
        scrapNode = findChildByName(self.node, "TOP/scrap_frame");
        self:setFrameNodeVisible(scrapNode);
    end

    self:updateScrapInfo();
end

-- 更新遗迹碎片信息
function UITopMenu:updateScrapInfo()
    local leftCountLabel = findChildByName(self.node, "TOP/scrap_frame/scrap_count");

    -- 第一栏显示的遗迹碎片
    local firstScrapNode = findChildByName(self.node, "TOP/first_scrap_frame");
    if firstScrapNode:isVisible() then
        local firstLabel = findChildByName(self.node, "TOP/first_scrap_frame/scrap_count");
        leftCountLabel = firstLabel;
    end

    -- 遗迹碎片
    local num = ItemM.getAmount(ME.user, ITEM_ID_RELIC);
    self:setTopMenuTextStyle(leftCountLabel);
    leftCountLabel:setString(tostring(num));
end

-- 显示总战力
function UITopMenu:showFightAbility()
    local fightAbilityNode = findChildByName(self.node, "TOP/fight_ability_frame");
    self:setFrameNodeVisible(fightAbilityNode);
    self:updateFightAbilityInfo();
end

-- 更新总战力
function UITopMenu:updateFightAbilityInfo()
    local leftCountLabel = findChildByName(self.node, "TOP/fight_ability_frame/fight_ability");
    -- 总战力
    local ability = SkyCombatM.calcArmyAbility();
    if UIMgr.getCurrentScene():isOpen("UIRelicUserInfo")
        or UIMgr.getCurrentScene():isOpen("UIRevengeUserInfo") then
        local prop = PropM.combine(ME.user, "rob_attrib", "fight_ability");
        ability = PropM.apply(prop, ability);
    end
    self:setTopMenuTextStyle(leftCountLabel);
    leftCountLabel:setString(tostring(ability));
end

-- 设置各信息结点的显隐
function UITopMenu:setFrameNodeVisible(curShowNode)
    for _, node in pairs(self.allFrameNode) do
        if curShowNode ~= nil and node:getName() == curShowNode:getName() then
            node:setVisible(true);
        else
            node:setVisible(false);
        end
    end
end

-- 更新飞艇雷达信息
function UITopMenu:updateAirShipRadar()
    local activedShip = NewAirShipM.getActiveAirShip() or 1;
    local maxRadar = NewAirShipM.query(activedShip, "max_target_num") or 0;

    local skyExplore = ME.user.dbase:query("sky_explore", {});
    local curRadar = #table.keys(skyExplore);

    local radarNode = findChildByName(self.node, "TOP/airship_radar_frame");
    for i = 1, 12 do
        local node = findChildByName(radarNode, "radar" .. i);
        if i > maxRadar then
            node:setVisible(false);
        elseif i > curRadar then
            node:loadTexture(getSmallAttribIconPath("radar2"));
            node:setVisible(true);
        else
            node:loadTexture(getSmallAttribIconPath("radar"));
            node:setVisible(true);
        end
    end
end

-- 更新英雄头像
function UITopMenu:redrawHeadIcon()
    local headImg = findChildByName(self.node, "TOP/frame/head_pic");

    -- 获取当前出战英雄
    local activeHero = ME.user:getActivePet();
    if not activeHero then
        return;
    end

    headImg:loadTexture(getHeroIconPath(activeHero:getIcon()));
end

-- 玩家升级的回调
function UITopMenu:whenUserLevelUp(args)

end

-- 更新活力剩余时间
function UITopMenu:updateLifeLeftTime()
    if ME.user:getMaxLife() <= ME.user.dbase:query("life", 0) then
        self.lifeLeftTimeNode:setVisible(false);
        return;
    end

    local leftTime = math.floor(UserM.getLifeRecoveryLeftTime());

    local secs = leftTime % 60;
    local mins = math.floor(leftTime / 60);
    local str = string.format("%02d:%02d", mins, secs);

    self.lifeLeftTimeNode:setString(str);
    self.lifeLeftTimeNode:setVisible(true);
end

-- 设置主界面头部文字的文本风格1
function UITopMenu:setTopMenuTextStyle(node)
    TextStyleM.setOutlineStyle(node, TextStyleM.TEXT_OUTLINE_SIZE, TextStyleM.TEXT_OUTLINE_COLOR_DARK);
    TextStyleM.setTextStyle(node, TextStyleM.TEXT_SIZE_MINI, TextStyleM.TEXT_COLOR_WHITE, true, -3, 1, true);
    node:setScaleX(1.2);
end

-- 设置主界面头部文字的文本风格2
function UITopMenu:setTopMenuTextStyle2(node)
    TextStyleM.setTextStyle(node, TextStyleM.TEXT_SIZE_MINI, TextStyleM.TEXT_COLOR_BRIGHT_YELLOW, true, -3, 1, true);
    node:setScaleX(1.2);
end

-- 设置主界面头部文字的文本风格3
function UITopMenu:setTopMenuTextStyle3(node)
    TextStyleM.setOutlineStyle(node, TextStyleM.TEXT_OUTLINE_SIZE, TextStyleM.TEXT_OUTLINE_COLOR_DARK);
    TextStyleM.setTextStyle(node, TextStyleM.TEXT_SIZE_MINI, TextStyleM.TEXT_COLOR_WHITE, true, -3, 1, true);
end

-- 设置主界面头部文字的文本风格4
function UITopMenu:setTopMenuTextStyle4(node)
    TextStyleM.setTextStyle(node, TextStyleM.TEXT_SIZE_MINI, TextStyleM.TEXT_COLOR_BRIGHT_YELLOW, true, -3, 1, true, nil, nil, true);
    node:setScaleX(1.2);
end

-- 开始倒计时
function UITopMenu:startFateCountingDown()
    if self.isFateCountingDown then
        return;
    end

    local socket = require "socket";

    self.fateLastTime = socket.gettime();

    local function countDown()
        local delay = 1;
        local leftTime = FateChainM.getFateLinkRecoveryLeftTime();
        if leftTime ~= 0 then
            -- 如果剩余时间超过了上限，此时客户端时间可能异常，请求服务器修正一下
            local totalTime = FateChainM.getFateRecoverTime();
            if leftTime > totalTime then
                trace("UITopMenu", "链接恢复剩余时间异常，当前：%d, 上限：%d。请求服务器修正", leftTime, totalTime);
                FateChainM.tryFateLinkRecover();
            else
                self.lastFateTry = nil;
                local elapse = socket.gettime() - self.fateLastTime;
                leftTime = leftTime - elapse;
                if leftTime <= 0 then
                    FateChainM.tryFateLinkRecover();
                    leftTime = 0;
                end

                FateChainM.setFateLinkRecoveryLeftTime(leftTime);
                self.fateLastTime = socket.gettime();
            end
        elseif FateChainM.getMaxLinkTimes() > ME.user.dbase:query("fate_link", 0) then
            -- 体力未满，并且超过10s显示为0，则每10s主动请求一次
            local elapse = socket.gettime() - self.fateLastTime;
            self.lastFateTry = self.lastFateTry or socket.gettime();
            if socket.gettime() - self.lastFateTry > 10 then
                FateChainM.tryFateLinkRecover();
                self.lastFateTry = socket.gettime();
            end
        end
        performWithDelay(self, countDown, delay);
    end
    performWithDelay(self, countDown, 1);

    self.isFateCountingDown = true;
end

-- 开始倒计时
function UITopMenu:startCountingDown()
    if self.isCountingDown then
        return;
    end

    local socket = require "socket";

    self.lastTime = socket.gettime();

    local function countDown()
        local delay = 1;
        local leftTime = UserM.getLifeRecoveryLeftTime();
        if leftTime ~= 0 then
            -- 如果剩余时间超过了上限，此时客户端时间可能异常，请求服务器修正一下
            local totalTime = UserM.getLifeRecoverTime();
            if leftTime > totalTime then
                trace("UITopMenu", "体力恢复剩余时间异常，当前：%d, 上限：%d。请求服务器修正", leftTime, totalTime);
                Operation.cmd_try_life_recovery();
            else
                self.lastTry = nil;
                local elapse = socket.gettime() - self.lastTime;
                leftTime = leftTime - elapse;
                if leftTime <= 0 then
                    Operation.cmd_try_life_recovery();
                    leftTime = 0;
                end

                UserM.setLifeRecoveryLeftTime(leftTime);
                self.lastTime = socket.gettime();
            end
        elseif ME.user:getMaxLife() > ME.user.dbase:query("life", 0) then
            -- 体力未满，并且超过10s显示为0，则每10s主动请求一次
            local elapse = socket.gettime() - self.lastTime;
            self.lastTry = self.lastTry or socket.gettime();
            if socket.gettime() - self.lastTry > 10 then
                Operation.cmd_try_life_recovery();
                self.lastTry = socket.gettime();
            end
        end
        performWithDelay(self, countDown, delay);
    end
    performWithDelay(self, countDown, 1);

    self.isCountingDown = true;
end

-- 飞入效果
function UITopMenu:flyIn()
    local offsetY = -500;
    self.panel:setPositionY(self.oldPanelPos.y - offsetY);

    local function play()
        local duration = 0.2;
        local moveDown = cc.EaseIn:create(cc.MoveBy:create(duration, cc.p(0, offsetY - 5)), 0.3);
        local moveUp = cc.EaseIn:create(cc.MoveBy:create(0.1, cc.p(0,  8)), 0.3);
        local moveDown2 = cc.EaseIn:create(cc.MoveBy:create(0.1, cc.p(0, -3)), 0.3);
        local action = cc.Sequence:create(moveDown ,moveUp, moveDown2);
        self.panel:stopAllActions();
        self.panel:runAction(action);
    end

    self.panel:stopAllActions();
    performWithDelay(self.panel, play, 0.2);
end

-- 飞出效果
function UITopMenu:flyOut()
    local duration = 0.2;
    self.panel:stopAllActions();
    local delay = cc.DelayTime:create(0.1);
    local move = cc.MoveTo:create(duration, cc.p(self.oldPanelPos.x, self.oldPanelPos.y + 500));
    self.panel:runAction(cc.Sequence:create(delay, move));
end

--------------------------------------
-- 显示顶部菜单内容
-- @param firstFrameType 第一栏类型
-- @param secondFrameType 第一栏类型
-- @param showEffect 默认为false，设置为true的时候，无论什么情况都会有飞入效果
function UITopMenu:show(firstFrameType, secondFrameType, headType, showEffect)
    setJumpStop("idleWorkerNumLabel", true);

    showEffect = showEffect or false;

    if showEffect or self.lastFirstFrame ~= firstFrameType or self.lastSecondFrame ~= secondFrameType then
        -- 先飞出
        self:flyOut();
    end

    self:resetBars();

    -- 头像框
    if headType == TOPMENU_FRAME_HEAD_AIRSHIP then
        self:showAirShipFrame();
    else
        self:showHeadFrame();
    end

    -- 第一行
    if firstFrameType == TOPMENU_FRAME_MONEY then
        self:showMoneyInfo();
    elseif firstFrameType == TOPMENU_FRAME_TREE then
        self:showTreeInfo();
    elseif firstFrameType == TOPMENU_FRAME_SP then
        self:showSpInfo();
    elseif firstFrameType == TOPMENU_FRAME_COPPER then
        self:showCopperInfo();
    elseif firstFrameType == TOPMENU_FRAME_AIRSHIP_SCORE then
        self:showAirShipScore();
    elseif firstFrameType == TOPMENU_FRAME_FIRST_RUINS_SCRAP then
        self:showRuinsScrap(true);
    elseif firstFrameType == TOPMENU_FRAME_RELIC_FRAGMENT then
        self:showRelicFragment();
    elseif firstFrameType == TOPMENU_FRAME_GEAR then
        self:showGearInfo();
    elseif firstFrameType == TOPMENU_FRAME_LADADUOMU_COIN then
        self:showLadaduomuCoin();
    elseif firstFrameType == TOPMENU_FRAME_ACTIVITY_DATA then
        self:showActivityData();
    elseif firstFrameType == TOPMENU_FRAME_ACTIVITY_EXCHANGE then
        self:showActivityExchange();
    elseif firstFrameType == TOPMENU_FRAME_FATE_CHAIN then
        self:showFateChainInfo();
    else
        error("不支持的firstFrameType类型");
    end

    -- 第二行
    if secondFrameType == TOPMENU_FRAME_LIFE then
        self:showLifeInfo();
    elseif secondFrameType == TOPMENU_FRAME_FRUIT then
        self:showFruitInfo();
    elseif secondFrameType == TOPMENU_FRAME_WORKER then
        self:showWorkerInfo();
    elseif secondFrameType == TOPMENU_FRAME_GEM then
        self:showGem();
    elseif secondFrameType == TOPMENU_FRAME_HERO then
        self:showHeroInfo();
    elseif secondFrameType == TOPMENU_FRAME_FEED then
        self:showFeedInfo();
    elseif secondFrameType == TOPMENU_FRAME_AIRSHIP_ATTRIB then
        self:showAirShipAttrib();
    elseif secondFrameType == TOPMENU_FRAME_AIRSHIP_RADAR then
        self:showAirShipRadar();
    elseif secondFrameType == TOPMENU_FRAME_RUINS_SCRAP then
        self:showRuinsScrap();
    elseif secondFrameType == TOPMENU_FRAME_FIGHT_ABILITY then
        self:showFightAbility();
    elseif secondFrameType == TOPMENU_FRAME_STATUE then
        -- 谜之雕像
        self:showStatue();
    elseif secondFrameType == TOPMENU_FRAME_AIRSHIP_ATTRIB2 then
        self:showAirShipAttrib2();
    elseif secondFrameType == TOPMENU_FRAME_ACTIVITY_TIMES then
        self:showActivityTimes();
    elseif secondFrameType == TOPMENU_FRAME_ENGINEERING_MANUAL then
        self:showManualNeeds();
    elseif secondFrameType == TOPMENU_FRAME_ROTINE_ACTIVITY then
        self:showRotineActivity();
    elseif secondFrameType == TOPMENU_FRAME_FATE_LINK then
        self:showFateLinkInfo();
    else
        error("不支持的secondFrameType类型");
    end

    if showEffect or self.lastFirstFrame ~= firstFrameType or self.lastSecondFrame ~= secondFrameType then
        -- 再飞入
        self:flyIn();
    end

    self.lastFirstFrame = firstFrameType;
    self.lastSecondFrame = secondFrameType;
end

-- 钻石修改事件
function UITopMenu:updateGemInfo()
    local gemNode = findChildByName(self.node, "TOP/gem_frame");
    local gemLabel = findChildByName(gemNode, "gem_text");
    local gemImg = findChildByName(gemNode, "gem_icon");

    local gemAmount = ME.user:queryAttrib("gem");

    if gemAmount <= self.gemAmount then
        gemLabel:setString(tostring(gemAmount));

        -- 更新钻石值
        self.gemAmount = gemAmount;
    else
        -- 钻石图标闪烁
        playEffect(gemImg, 1235, 21, 20);

        -- 1.变大
        local upTime    = 0.25/4;
        local up2Time   = 0.25/4;
        local scaleUp   = cc.ScaleTo:create(upTime, 1.1);
        local scaleUp2  = cc.ScaleTo:create(up2Time, 1.2);

        local seq1 = cc.Sequence:create(scaleUp, scaleUp2);
        local action1 = cc.Spawn:create(seq1);

        -- 2.短暂停顿
        local delayTime = 0.2/4;
        local delay = cc.DelayTime:create(delayTime);

        -- 3.变小
        local downTime  = 0.25/4;
        local down2Time = 0.25/4;
        local scaleDown = cc.ScaleTo:create(downTime, 1.1);
        local scaleDown2 = cc.ScaleTo:create(down2Time, 1);
        local seq2 = cc.Sequence:create(scaleDown, scaleDown2);
        local action2 = cc.Spawn:create(seq2);

        local sequenceNodeAction = cc.Sequence:create(action1, delay, action2);
        -- SLIMEC-1847 中修改为闪烁即可
        -- gemImg:runAction(sequenceNodeAction);

        gemUpScrolling(gemLabel, gemAmount, self.gemAmount, nil, 30);

        self.gemAmount = gemAmount;

        -- 文字变大特效
        commonTextEffect(gemLabel);
    end
end

-- 显示谜の雕像
function UITopMenu:showStatue(firstFrame)
    local statueNode = findChildByName(self.node, "TOP/statue_frame");
    self:setFrameNodeVisible(statueNode);

    self:updateStatueInfo();
end

-- 更新雕像信息
function UITopMenu:updateStatueInfo()
    local leftCountLabel = findChildByName(self.node, "TOP/statue_frame/statue_count");

    -- 雕像数量
    local num = ItemM.getAmount(ME.user, ITEM_ID_STATUE);
    self:setTopMenuTextStyle(leftCountLabel);
    leftCountLabel:setString(tostring(num));
end

-- 重新调整大小
function UITopMenu:resize()
    local node = self.node;

    local frameSize = AlignM.frameSize;

    local w = frameSize.width;
    local h = frameSize.height;

    local panel = findChildByName(node, "TOP");
    panel:setPosition(w / 2, h);

    panel:setScale(math.min(w / DESIGN_WIDTH, h / DESIGN_HEIGHT));
    self.oldPanelPos = cc.p(panel:getPosition());
    self.panel = panel;
end


-- 显示飞艇头像
function UITopMenu:showAirShipFrame()
    local headNode = findChildByName(self.node, "TOP/frame");
    local airShipNode = findChildByName(self.node, "TOP/airship_frame");

    -- 必须天空之城指引结束了才显示
    if not NewAirShipM.isFinishGuide() then
        -- 指引还没结束，还是显示冈布奥头像
        self:showHeadFrame();
        return;
    end

    headNode:setVisible(false);
    airShipNode:setVisible(true);

    self:redrawAirShipFrame();
end

-- 显示冈布奥头像
function UITopMenu:showHeadFrame()
    local headNode = findChildByName(self.node, "TOP/frame");
    local airShipNode = findChildByName(self.node, "TOP/airship_frame");
    headNode:setVisible(true);
    airShipNode:setVisible(false);
end

-- 重绘飞艇头像
function UITopMenu:redrawAirShipFrame()
    local frame = findChildByName(self.node, "TOP/airship_frame");
    local airshipImg = findChildByName(self.node, "TOP/airship_frame/airship");
    local campImg = findChildByName(self.node, "TOP/airship_frame/camp");

    -- 获取当前出战的飞艇和阵营
    local activeShip = NewAirShipM.getActiveAirShip();
    local activeGroup = ME.user.dbase:query("activedSkyGroup");

    if not activeShip or not activeGroup then
        return;
    end

    frame:loadTexture(getSkyCityPath("title_frame"));
    airshipImg:loadTexture(getSkyCityTitleAirshipPath(activeShip));
    campImg:loadTexture(getSkyCityTitleCampPath(activeGroup));
end

-- 播放飞艇框效果
function UITopMenu:playAirShipEffect(type)
    local frame = findChildByName(self.node, "TOP/airship_frame");

    playShakeEffect(frame, 0.05, 5, 2);
end

-- 计算一个数是几位数
function calcDigit(num)
    local digit = 1;
    while num / 10 >= 10  do
        num = num / 10;
        digit = digit + 1;
    end
    return digit;
end

-- 设置显示的天空活动id
function UITopMenu:setSkyActivityId(id)
    skyActivityId = id;
end

-- 设置兑换的货币
function UITopMenu:setExchangeCurrency(classId)
    trace("UITopMenu", "setExchangeCurrency: classId = " .. tostring(classId));
    exchangeCurrency = classId;
end

-- 显示活动数据
function UITopMenu:showActivityData()
    local activityDataNode = findChildByName(self.node, "TOP/activity_data_frame");
    self:setTopFrameNodeVisible(activityDataNode);

    self:updateActivityData();
end

-- 更新活动数据
function UITopMenu:updateActivityData()
    local node          = findChildByName(self.node, "TOP/activity_data_frame");

    if not node:isVisible() then
        return;
    end

    local scoreLabel    = findChildByName(node, "score_text");
    local medalLabel    = findChildByName(node, "medal_text");
    local activityData  = SkyActivityM.getActivityData(skyActivityId);
    local score         = activityData["score"] or 0;
    local medalClassId  = SkyActivityM.query(skyActivityId, "medal_class_id");
    local medal         = ItemM.getAmount(ME.user, medalClassId);

    -- 积分
    self:setTopMenuTextStyle(scoreLabel);
    scoreLabel:setString(score);

    -- 剩余勋章
    self:setTopMenuTextStyle(medalLabel);
    medalLabel:setString(medal);
end

-- 显示活动次数
function UITopMenu:showActivityTimes()
    local activityTimesNode = findChildByName(self.node, "TOP/activity_times_frame");
    self:setFrameNodeVisible(activityTimesNode);

    self:updateActivityTimes();

    self:updateActivityTimesRecoverTime();

    self:startUpdateLeftTime();
end

-- 更新活动次数
function UITopMenu:updateActivityTimes()
    local node = findChildByName(self.node, "TOP/activity_times_frame");
    if node:isVisible() then
        -- 显示体力图标
        local maxLife = SkyActivityM.getMaxTimes();
        local activityData  = SkyActivityM.getActivityData(skyActivityId);
        local curLife = activityData["times"] or 0;
        local status = ActivityM.getActivityStatus(ActivityM.getActivityInfo(skyActivityId));

        if status == ACTIVITY_STATUS_END or status == ACTIVITY_STATUS_CLOSE then
            curLife = 0;
        end

        for i = 1, 9 do
            local iconImage = findChildByName(node, "life"..i);
            iconImage:loadTexture(getSmallAttribIconPath("attack_times"));
            if i <= curLife then
                -- 亮着
                iconImage:setVisible(true);
            elseif i <= maxLife then
                -- 灰色
                iconImage:setVisible(true);
                iconImage.grayMode = false;
                setGrayMode(iconImage, true);
            else
                -- 不可见
                iconImage:setVisible(false);
            end
        end

        if curLife > maxLife then
            for i = maxLife + 1, curLife do
               local iconImage = findChildByName(node, "life"..i);
               iconImage:loadTexture(getSmallAttribIconPath("attack_times"));

                iconImage:setVisible(true);
            end
        end
    end
end

-- 更新活动次数恢复时间
function UITopMenu:updateActivityTimesRecoverTime()
    local node = findChildByName(self.node, "TOP/activity_times_frame");
    if node:isVisible() then
        local timeNode      = findChildByName(node, "recovery_left_time");
        local activityData  = SkyActivityM.getActivityData(skyActivityId);
        local status = ActivityM.getActivityStatus(ActivityM.getActivityInfo(skyActivityId));

        if status == ACTIVITY_STATUS_END or status == ACTIVITY_STATUS_CLOSE then
            timeNode:setVisible(true);
            timeNode:setString("--:--");
            return;
        end

        if not activityData["recover_time"] or
            activityData["times"] >= SkyActivityM.getMaxTimes() then
            timeNode:setVisible(false);
        else
            timeNode:setVisible(true);

            local recoverTime = activityData["recover_time"];
            local leftTime = recoverTime + 3600 - TimeM.getServerTime();

            if leftTime < 0 then
                leftTime = 0;
            end
            local secs = leftTime % 60;
            local mins = math.floor(leftTime / 60);
            local str = string.format("%02d:%02d", mins, secs);

            timeNode:setString(str);
        end
    end
end

-- 更新活动次数恢复时间
function UITopMenu:startUpdateLeftTime()
    local node = findChildByName(self.node, "TOP/activity_times_frame");
    if not node:isVisible() then
        return;
    end

    local function leftTimeRefresh()
        self:updateActivityTimesRecoverTime();

        -- 每一秒去更新一下活动袭击次数恢复时间
        performWithDelay(node, leftTimeRefresh, 1);
    end

    leftTimeRefresh();
end

-- 显示工程学手册需要的物品信息
function UITopMenu:showManualNeeds()
    local manualNode = findChildByName(self.node, "TOP/engineering_manual_frame");
    self:setFrameNodeVisible(manualNode);

    -- 获取需要的物品
    local items = FormulaM.invoke("CALC_MANUAL_NEED");

    -- 图片的路径
    local pathList = {"honor_scrap20", "honor_scrap32", "honor_scrap35", "honor_scrap38"};

    -- 绘制信息
    for index, classId in ipairs(items) do
        local icon = findChildByName(manualNode, "icon" .. index);
        icon:loadTexture(getItemIconPath(classId));
        icon:setScale(0.6);

        local valueLabel = findChildByName(manualNode, "value" .. index);
        self:setTopMenuTextStyle(valueLabel);
        valueLabel:setString(ItemM.getAmount(ME.user, classId));
    end
end

-- 更新工程学手册需要的物品信息
function UITopMenu:updateManualNeeds()
    local manualNode = findChildByName(self.node, "TOP/engineering_manual_frame");

    -- 获取需要的物品
    local items = FormulaM.invoke("CALC_MANUAL_NEED");

    -- 绘制信息
    for index, classId in ipairs(items) do
        local valueLabel = findChildByName(manualNode, "value" .. index);
        valueLabel:setString(ItemM.getAmount(ME.user, classId));
    end
end

-- 显示常规活动
function UITopMenu:showRotineActivity()
    local rotineNode = findChildByName(self.node, "TOP/rotine_activity_frame");
    self:setFrameNodeVisible(rotineNode);

    self:updateRotineActivity();
end

-- 更新常规活动信息
function UITopMenu:updateRotineActivity()
    local rotineNode = findChildByName(self.node, "TOP/rotine_activity_frame");

    local attribInfo = RotineActivityM.getAttribInfo();
    local iconName;
    if attribInfo[1] == "rotine_hoe" then
        iconName = "small_hoe";
    else
        iconName = "small_token";
    end

    -- 绘制信息
    local icon = findChildByName(rotineNode, "icon");
    icon:loadTexture(getSmallAttribIconPath(iconName));

    local valueLabel = findChildByName(rotineNode, "value");
    self:setTopMenuTextStyle(valueLabel);
    valueLabel:setString(attribInfo[2]);
end

-- 显示链接信息
function UITopMenu:showFateChainInfo()
    local fateChainNode = findChildByName(self.node, "TOP/fate_chain_frame");
    self:setTopFrameNodeVisible(fateChainNode);

    self:updateFateChainInfo();
end

-- 更新链接信息
function UITopMenu:updateFateChainInfo()
    local info = FateChainM.getMyFateListInfo();

    local fateChainNode = findChildByName(self.node, "TOP/fate_chain_frame");
    if not self.fateChainText then
        self.fateChainText = findChildByName(fateChainNode, "fate_chain_text");
    end

    local fateChainIcon = findChildByName(fateChainNode, "fate_chain_bg");
    fateChainIcon:loadTexture(getSmallAttribIconPath("fate_achieve"));

    local text = string.format(getLocStr("fate_value_format"), info[2], info[1]);
    self:setTopMenuTextStyle(self.fateChainText);
    self.fateChainText = applyString(self.fateChainText, text);
end

-- 显示命运的链信息
function UITopMenu:showFateLinkInfo()
    local linkNode = findChildByName(self.node, "TOP/fate_link_frame");
    self:setFrameNodeVisible(linkNode);

    self:updateProps();

    self:startFateCountingDown();

    self:checkPauseState();
end

-- 更新命运之链剩余时间
function UITopMenu:updateFateLinkLeftTime()
    if FateChainM.getMaxLinkTimes() <= ME.user.dbase:query("fate_link", 0) then
        self.fateLinkTimeNode:setVisible(false);
        return;
    end

    local leftTime = math.floor(FateChainM.getFateLinkRecoveryLeftTime());

    local secs = leftTime % 60;
    local mins = math.floor(leftTime / 60);
    local str = string.format("%02d:%02d", mins, secs);

    self.fateLinkTimeNode:setString(str);
    self.fateLinkTimeNode:setVisible(true);
end

return UITopMenu;
